package org.jim.server.command.handler;

import org.apache.commons.collections4.CollectionUtils;
import org.jim.core.ImChannelContext;
import org.jim.core.ImPacket;
import org.jim.core.ImStatus;
import org.jim.core.config.ImConfig;
import org.jim.core.exception.ImException;
import org.jim.core.packets.pub.consts.Command;
import org.jim.core.packets.pub.pojo.Group;
import org.jim.core.packets.cs.user.command.LoginReqCmd;
import org.jim.core.packets.cs.user.command.LoginRespCmd;
import org.jim.core.packets.pub.pojo.JimUser;
import org.jim.core.helper.MessageHelper;
import org.jim.core.utils.JsonKit;
import org.jim.server.ImServerChannelContext;
import org.jim.server.JimServerAPI;
import org.jim.server.command.AbstractCmdHandler;
import org.jim.server.command.CommandHandler;
import org.jim.server.command.CommandManager;
import org.jim.server.config.ImServerConfig;
import org.jim.server.processor.login.LoginCmdProcessor;
import org.jim.server.protocol.ProtocolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Objects;

/**
 * 登录消息命令处理器
 *
 * @author WChao
 * @date 2018年4月10日 下午2:40:07
 */
@CommandHandler(cmd = Command.COMMAND_LOGIN_REQ,cmdProcessorClasses = {LoginCmdProcessor.class})
public class LoginReqHandler extends AbstractCmdHandler {

    private static Logger log = LoggerFactory.getLogger(LoginReqHandler.class);

    @Override
    public ImPacket handler(ImPacket packet, ImChannelContext imChannelContext) throws ImException {

        ImServerChannelContext imServerChannelContext = (ImServerChannelContext) imChannelContext;
        //请求中构建出登录请求对象
        LoginReqCmd loginReqBody = JsonKit.toBean(packet.getBody(), LoginReqCmd.class);
        //执行登陆逻辑
        LoginCmdProcessor loginCmdProcessor = this.getSingleProcessor(LoginCmdProcessor.class);
        LoginRespCmd loginRespBody = doLogin(imChannelContext, loginCmdProcessor, loginReqBody);
        JimUser user = loginRespBody.getUser();
        //绑定用户
        JimServerAPI.bindUser(imServerChannelContext, user);
        //初始化绑定或者解绑群组;
        initGroup(imChannelContext, user);
        //成功后处理
        loginCmdProcessor.onSuccess(user, imChannelContext);
        //响应信息
        return ProtocolManager.Converter.respPacket(loginRespBody, imChannelContext);
    }

    /**
     * 根据用户配置的自定义登录处理器获取业务组装的User信息
     *
     * @param imChannelContext  通道上下文
     * @param loginCmdProcessor 登录自定义业务处理器
     * @param loginReqBody      登录请求体
     * @return 用户组装的User信息
     * @throws ImException
     */
    private LoginRespCmd doLogin(ImChannelContext imChannelContext, LoginCmdProcessor loginCmdProcessor, LoginReqCmd loginReqBody) throws ImException {
        //如果没有命令处理器就构建一个用户信息
        if (Objects.isNull(loginCmdProcessor)) {
            return LoginRespCmd.failed();
        }
        //执行登陆
        LoginRespCmd loginRespBody = loginCmdProcessor.doLogin(loginReqBody, imChannelContext);

        //登陆不成功,就返回一个空的user
        if (loginRespBody.getCode() != ImStatus.C10007.getCode()) {
            log.error("login failed, userId:{}, password:{}", loginReqBody.getUsername(), loginReqBody.getPassword());
            loginCmdProcessor.onFailed(imChannelContext);
            JimServerAPI.bSend(imChannelContext, ProtocolManager.Converter.respPacket(loginRespBody, imChannelContext));
            JimServerAPI.remove(imChannelContext, "username or token is incorrect");
        }
        //返回登陆后的user对象
        return loginRespBody;
    }

    /**
     * 初始化绑定或者解绑群组;
     */
    public void initGroup(ImChannelContext imChannelContext, JimUser user) throws ImException {
        String username = user.getUsername();
        List<Group> groups = user.getGroups();
        if (CollectionUtils.isEmpty(groups)) return;
        ImServerConfig imServerConfig = ImConfig.Global.get();
        boolean isStore = ImServerConfig.ON.equals(imServerConfig.getIsStore());
        MessageHelper messageHelper = imServerConfig.getMessageHelper();
        List<String> groupIds = null;
        if (isStore) {
            //获取群的所有ID
            groupIds = messageHelper.getGroupHelper().getGroups(username);
        }
        //绑定群组
        for (Group group : groups) {
            if (isStore && CollectionUtils.isNotEmpty(groupIds)) {
                groupIds.remove(group.getGroupId());
            }
            ImPacket groupPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_REQ, JsonKit.toJsonBytes(group));
            try {
                JoinGroupReqHandler joinGroupReqHandler = CommandManager.getCommand(Command.COMMAND_JOIN_GROUP_REQ, JoinGroupReqHandler.class);
                joinGroupReqHandler.handler(groupPacket, imChannelContext);
            } catch (Exception e) {
                log.error(e.toString(), e);
            }
        }
        //解绑群组
        if (isStore && groupIds != null) {
            for (String groupId : groupIds) {
                messageHelper.getBindListener().onAfterGroupUnbind(imChannelContext, Group.newBuilder().groupId(groupId).build());
            }
        }
    }

    @Override
    public Command command() {
        return Command.COMMAND_LOGIN_REQ;
    }

}
